#include "vector3.h"

vector3::vector3(void)
{
        x = y = z = 0.0f;
}

vector3::~vector3(void)
{
}

vector3::vector3(double xp, double yp, double zp){
        x = xp;
        y = yp;
        z = zp;
}

void vector3::setX(double i){ x = i; }
void vector3::setY(double i){ y = i; }
void vector3::setZ(double i){ z = i; }

void vector3::addX(double i){ x += i; }
void vector3::addY(double i){ y += i; }
void vector3::addZ(double i){ z += i; }

double vector3::getX(){ return x; }
double vector3::getY(){ return y; }
double vector3::getZ(){ return z; }

vector3 vector3::getVector(){ return *this; }

vector3 vector3::operator +(vector3 rhs){
        return vector3(x+rhs.x, y+rhs.y, z+rhs.z);
}

vector3 vector3::operator -(vector3 rhs){
        return vector3(x-rhs.getX(), y-rhs.getY(), z-rhs.getZ());
}

vector3 vector3::operator *(double rhs){
        return vector3(x*rhs, y*rhs, z*rhs);
}

vector3 vector3::operator *(int rhs){
        return vector3(x*rhs, y*rhs, z*rhs);
}

vector3 vector3::operator *(vector3 rhs){
        return vector3(x*rhs.getX(), y*rhs.getY(), z*rhs.getZ());
}

vector3 vector3::operator /(double rhs){
        return vector3(x/rhs, y/rhs, z/rhs);
}

vector3 vector3::operator /(int rhs){
        return vector3(x/rhs, y/rhs, z/rhs);
}

vector3& vector3::operator+= (const vector3 rhs)
{
        x += rhs.x;
		y += rhs.y;
		z += rhs.z;
		return *this;
}

vector3& vector3::operator-= (const vector3 rhs)
{
        x -= rhs.x;
		y -= rhs.y;
		z -= rhs.z;
		return *this;
}


bool vector3::operator ==(vector3 rhs){
        if(x==rhs.getX() && y==rhs.getY() && z==rhs.getZ())
                return true;
        return false;
}

void vector3::normalize(){
        double l = length();
		x = x/l;
		y = y/l;
		z = z/l;
}

vector3 vector3::normalized(){
	double l = length();
	return vector3(x/l, y/l, z/l);
}

vector3 vector3::unitFrom(vector3 v){
        vector3 vec(x-v.getX(), y-v.getY(), z-v.getZ());
        return vec.normalized();
}

double vector3::dot(vector3 i){ return x*i.getX() + y*i.getY() + z*i.getZ(); }

vector3 vector3::cross(vector3 i)
{
        vector3 normal;
        normal.setX(y * i.getZ() - z * i.getY());
        normal.setY(z * i.getX() - x * i.getZ());
        normal.setZ(x * i.getY() - y * i.getX());

        return normal;
}

double vector3::angle(vector3 vec1, vector3 vec2)
{
	double angle = acos(vec1.normalized().dot(vec2.normalized()));
	vector3 determinator = vec1.cross(vec1.cross(vec2));
	double dotDetermine = determinator.normalized().dot(vec2);
	
	if (dotDetermine >= 0)
	{
		return -angle;
	}
	else
	{
		return angle;
	}
}

double vector3::length(){
        return sqrt(x*x + y*y + z*z);
}

double vector3::distanceFrom(vector3 v){
	return sqrt( pow( v.getX() - x , 2 ) + pow( v.getY() - y, 2 ) + pow( v.getZ() - z , 2 ) );
}

vector3 vector3::Up(void)
{
	return vector3(0.0, 1.0, 0.0);
}

vector3 vector3::Right(void)
{
	return vector3(1.0, 0.0, 0.0);
}

vector3 vector3::In(void)
{
	return vector3(0.0, 0.0, 1.0);
}

vector3 vector3::Zero(void)
{
	return vector3(0.0, 0.0f, 0.0);
}
